﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading.Tasks;
using HotShot.Entities;
using HotShot.Service.Entities;
using HotShot.Entities.Messages;
using HotShot.Service.BusinessLogic.MessageProcessors;
using System.Configuration;

namespace HotShot.Service.BusinessLogic
{
    public class MessagingLogic
    {
        public static MessagingLogic Current = new MessagingLogic();

        Dictionary<string, MessageProcessorBase> _processorTable;

        public int StoreTotal = 1;
        public int StoreThreshold = 1;
        public int RetrieveTotal = 1;
        public int RetrieveThreshold = 1;

        public MessagingLogic()
        {
            _processorTable = new Dictionary<string, MessageProcessorBase> {
                { "InitNode.broadcast", new InitNodeBroadcastProcessor() },
                { "InitNode", new InitNodeProcessor() },
                { "GetKnownNodes.broadcast", new GetKnownNodesProcessor() },
                { "GetKnownNodes", new GetKnownNodesProcessor() },
                { "KnownNodes.broadcast", new KnownNodesProcessor() },
                { "KnownNodes", new KnownNodesProcessor() },
                { "Ping.broadcast", new PingProcessor() },
                { "Ping", new PingProcessor() },
                { "Store.broadcast", new StoreBroadcastProcessor() },
                { "Store", new StoreProcessor() },
                { "StoreResult", new StoreResultProcessor() },
                { "Retrieve.broadcast", new RetrieveBroadcastProcessor() },
                { "Retrieve", new RetrieveProcessor() },
                { "RetrieveResultInternal", new RetrieveResultInternalProcessor() },
            };

            int i;
            if (Int32.TryParse(ConfigurationManager.AppSettings["MessagingLogic.StoreTotal"], out i)) StoreTotal = i;
            if (Int32.TryParse(ConfigurationManager.AppSettings["MessagingLogic.StoreThreshold"], out i)) StoreThreshold = i;
            if (Int32.TryParse(ConfigurationManager.AppSettings["MessagingLogic.RetrieveTotal"], out i)) RetrieveTotal = i;
            if (Int32.TryParse(ConfigurationManager.AppSettings["MessagingLogic.RetrieveThreshold"], out i)) RetrieveThreshold = i;
        }

        public void Initialize()
        {
        }

        public void ProcessMessage(BaseMessage message, string correlationId, bool isBroadcast)
        {
            string messageType = message.MessageType + (isBroadcast ? ".broadcast" : "");

            if(Common.TraceMessages) 
                Trace.WriteLine("Processing " + (isBroadcast ? "broadcast " : "") + "message: " + message.MessageType + " from " + message.SenderAddress);

            ClusterProcessorLogic.Current.UpdateTicks(message.SenderAddress, message.Ticks);

            if (!_processorTable.ContainsKey(messageType))
                throw new ApplicationException("Processor not found for " + messageType);

            _processorTable[messageType].ProcessMessage(message, correlationId);
        }


    }
}